load("@aspect_rules_esbuild//esbuild:defs.bzl", "esbuild")
load("@aspect_rules_js//js:defs.bzl", "js_binary", "js_run_binary")
load("@aspect_rules_ts//ts:defs.bzl", rules_js_tsconfig = "ts_config")
load("@bazel_skylib//rules:build_test.bzl", "build_test")
load("//src/cdk:config.bzl", "CDK_TARGETS")
load("//src/cdk-experimental:config.bzl", "CDK_EXPERIMENTAL_TARGETS")
load("//src/components-examples:config.bzl", "ALL_EXAMPLES")
load("//src/material:config.bzl", "MATERIAL_TARGETS")
load("//src/material-experimental:config.bzl", "MATERIAL_EXPERIMENTAL_TARGETS")
load("//tools:defaults.bzl", "http_server", "ng_project", "protractor_web_test_suite", "sass_binary", "ts_project")

package(default_visibility = ["//visibility:public"])

rules_js_tsconfig(
    name = "tsconfig",
    src = "tsconfig.json",
    deps = [
        "//:node_modules/@types/node",
        "//src:build-tsconfig",
    ],
)

ng_project(
    name = "kitchen-sink",
    srcs = [
        "kitchen-sink/kitchen-sink.ts",
    ],
    assets = [
        "kitchen-sink/kitchen-sink.html",
    ],
    deps = [
        "//:node_modules/@angular/common",
        "//:node_modules/@angular/core",
        "//:node_modules/@angular/platform-server",
        "//:node_modules/rxjs",
        "//src/google-maps",
        "//src/youtube-player",
    ] + CDK_TARGETS + CDK_EXPERIMENTAL_TARGETS + MATERIAL_TARGETS + MATERIAL_EXPERIMENTAL_TARGETS + ALL_EXAMPLES,
)

ts_project(
    name = "client_lib",
    srcs = [
        "main.ts",
    ],
    tsconfig = ":tsconfig",
    deps = [
        ":kitchen-sink",
        "//:node_modules/@angular/platform-browser",
    ],
)

ts_project(
    name = "prerender_lib",
    srcs = [
        "prerender.ts",
    ],
    tsconfig = ":tsconfig",
    deps = [
        ":kitchen-sink",
        "//:node_modules/@angular/compiler",
        "//:node_modules/@angular/core",
        "//:node_modules/@angular/platform-browser",
        "//:node_modules/@angular/platform-server",
        "//:node_modules/@bazel/runfiles",
        "//:node_modules/@types/node",
        "//:node_modules/zone.js",
    ],
)

sass_binary(
    name = "styles_scss",
    src = "styles.scss",
    deps = [
        "//src/material:sass_lib",
        "//src/material-experimental:sass_lib",
    ],
)

js_binary(
    name = "prerender",
    data = [
        "index-source.html",
        ":prerender_bundle",
        ":styles_scss",
    ],
    entry_point = ":prerender_bundle.js",
)

esbuild(
    name = "client_bundle",
    srcs = ["//src:build-tsconfig"],
    config = "//src:esbuild-linked-config",
    entry_points = [":main.js"],
    platform = "browser",
    target = "es2016",
    deps = [
        ":client_lib",
    ],
)

esbuild(
    name = "prerender_bundle",
    srcs = ["//src:build-tsconfig"],
    config = "//src:esbuild-linked-config",
    entry_point = ":prerender.js",
    platform = "node",
    # We cannot use `ES2017` or higher as that would result in `async/await` not being downleveled.
    # ZoneJS needs to be able to intercept these as otherwise change detection would not work properly.
    target = "es2016",
    deps = [
        ":prerender_lib",
    ],
)

js_run_binary(
    name = "prerender_test_bin",
    outs = ["index-prerendered.html"],
    args = ["../../../$@"],
    tool = ":prerender",
)

js_run_binary(
    name = "debug_prerender_bin",
    # Note: the file needs to be called `index.html` specifically so the server can pick it up.
    outs = ["index.html"],
    args = [
        "../../../$@",
        "--debug",  # Disables some testing behavior that can be annoying while debugging.
    ],
    tool = ":prerender",
)

build_test(
    name = "prerender_test",
    targets = [
        ":prerender_test_bin",
    ],
)

http_server(
    name = "server",
    srcs = [
        ":debug_prerender_bin",
        "//:node_modules/zone.js",
    ],
    additional_root_paths = [
        "angular_material/",
    ],
    tags = ["manual"],
    deps = [
        ":client_bundle",
        ":styles_scss",
    ],
)

ts_project(
    name = "hydration_e2e_tests_sources",
    testonly = True,
    srcs = ["hydration.e2e.spec.ts"],
    deps = ["//:node_modules/protractor"],
)

protractor_web_test_suite(
    name = "hydration_e2e_tests",
    server = ":server",
    tags = ["e2e"],
    deps = [
        ":hydration_e2e_tests_sources",
    ],
)
